import CanvasTools from "@/components/SmartCanvasWidget/CanvasTools";
import {Application, Container, Graphics, RenderTexture, Sprite} from "pixi.js";

// 画笔配置数据接口
interface BrushConfigInterface
{
    width?: number; // 画笔宽度
    color?: number | string; // 画笔颜色
}

// 模式
type Mode = "brush" | "eraser";

/**
 * 画笔工具类
 * */
class CanvasPainting
{
    // 当前对象
    private static instance: CanvasPainting;

    // 当前画笔容器对象
    private static brushContainer: Container<any>;

    // 工具
    private static tools: any;

    // 实例
    private static app: Application;

    // 当前模式
    private static mode: Mode = "brush";

    // 当前是否激活
    private static enable: boolean = true;

    // 当前激活时的层级
    private static zIndex: number = 999;

    // 当前未激活时的层级
    private static zIndexUnable: number = 0;

    // 画笔轨迹透明度
    private static trackAlpha: number = 0.6;

    // 工具配置
    private static config: Record<string, any> = {
        // 画笔配置
        brush: {
            width: 32, // 画笔宽度
            color: 0xffffff, // 画笔颜色
            alpha: 1 // 画笔透明度
        }, // 橡皮擦配置
        eraser: {
            width: 32, // 橡皮擦宽度
            color: 0x000000, // 橡皮擦颜色
            alpha: 1 // 橡皮擦透明度
        }
    };

    /**
     * 构造函数
     * @param {Object} argumentsList 参数列表 {app(对象): Application; options(配置): Record<string, any>}
     * */
    constructor(argumentsList: Record<string, any>)
    {
        // 实例
        CanvasPainting.app = argumentsList.app;

        // 实例化工具
        CanvasPainting.tools = new CanvasTools({
            app: argumentsList.app
        });

        // 当前对象
        CanvasPainting.instance = this;
    }

    /**
     * 画笔
     * @param {String} mode 模式 brush: 画笔 | eraser: 橡皮擦
     * @param {BrushConfigInterface} options 配置项（width: 画笔宽度 | color: 画笔颜色）
     * */
    painting(mode: string, options?: BrushConfigInterface): void
    {
        // 动态设置模式
        CanvasPainting.mode = mode as Mode;

        // 设置画笔配置
        if (options && !isEmpty(options))
        {
            // 画笔宽度
            if (options.width)
            {
                CanvasPainting.config[mode].width = options.width;
            }

            // 画笔颜色
            if (options.color)
            {
                CanvasPainting.config[mode].color = options.color;
            }
        }

        // 获取重绘容器
        const drawContainer = CanvasPainting.tools.getApplicationSourceData(CanvasPainting.app.stage, "drawing-painting-container") as Container<any>;

        // 如果没有重绘容器，则初始化画笔
        if (!drawContainer)
        {
            // 初始化画笔
            this.initPainting();
        }
    }

    /**
     * 禁用画笔
     * */
    disable(): void
    {
        // 设置画笔未激活
        CanvasPainting.enable = false;

        // 设置当前画笔容器对象的层级
        if (CanvasPainting.brushContainer)
        {
            CanvasPainting.brushContainer.zIndex = CanvasPainting.zIndexUnable;
        }
    }

    /**
     * 启用画笔
     * */
    enable(): void
    {
        // 设置画笔激活
        CanvasPainting.enable = true;

        // 设置当前画笔容器对象的层级
        if (CanvasPainting.brushContainer)
        {
            CanvasPainting.brushContainer.zIndex = CanvasPainting.zIndex;
        }
    }

    /**
     * 初始化画笔
     * */
    private initPainting(): void
    {
        // 获取画板资源容器（存放背景图等基础元素）
        const boardContainer = CanvasPainting.tools.getApplicationSourceData(CanvasPainting.app.stage, "drawing-board-assets-container") as Container<any>;

        if (!boardContainer)
        {
            return;
        }

        // 获取扩展层
        const extendContainer = CanvasPainting.tools.getApplicationSourceData(CanvasPainting.app.stage, "image-extend-container") as Container<any>;

        if (!extendContainer)
        {
            return;
        }

        // 获取容器中的子元素（通常第一个元素是背景图）
        const children: any[] = boardContainer.children;

        if (!children || !children.length)
        {
            return;
        }

        // 获取底层背景图精灵对象（作为画布底板）
        const backgroundImage = children[0] as Sprite;

        if (!backgroundImage)
        {
            return;
        }

        // 创建绘制层容器（用于承载绘制层和临时绘图对象）
        const spriteContainer = new Container();

        // 对齐背景图位置
        spriteContainer.position.set(backgroundImage.x, backgroundImage.y);

        // 设置别名
        spriteContainer.label = "drawing-painting-container";

        // 当前背景精灵做为蒙版
        spriteContainer.mask = new Sprite(CanvasPainting.tools.createGridTexture({width: backgroundImage.width, height: backgroundImage.height, gap: 16}));

        // 设置当前激活时的层级
        spriteContainer.zIndex = CanvasPainting.zIndex;

        // 缓存当前画笔容器对象
        CanvasPainting.brushContainer = spriteContainer;

        // 创建离屏渲染纹理（作为绘制层的画布）
        const drawingTexture = RenderTexture.create({
            width: backgroundImage.width,
            height: backgroundImage.height,
            resolution: CanvasPainting.app.renderer.resolution,
            antialias: true // 开启抗锯齿
        });

        // 初始化透明画布（RGBA: 0,0,0,0 表示完全透明）
        CanvasPainting.app.renderer.render({
            container: spriteContainer,
            target: drawingTexture,
            clear: true,
            clearColor: [0, 0, 0, 0]
        });

        // 创建显示精灵（将离屏纹理实时显示在画布上）
        const drawingSprite = new Sprite(drawingTexture);

        // 使用正常混合模式
        drawingSprite.blendMode = "normal";

        // 完全不透明显示
        drawingSprite.alpha = CanvasPainting.trackAlpha;

        // 创建临时绘图容器（用于记录实时绘制笔触）
        const drawingContainer = new Container();

        // 创建绘图对象（实际绘制操作在此对象进行）
        const graphics = new Graphics();

        // 添加到绘图容器中
        drawingContainer.addChild(graphics);

        // 添加到精灵图容器中（层级顺序：先背景后绘制层）
        spriteContainer.addChild(drawingSprite, drawingContainer);

        // 绘图状态变量
        let isDrawing = false;

        // 事件类型
        spriteContainer.eventMode = "static";

        // 绑定事件
        spriteContainer.on("pointerenter", pointerEnterHandler).on("pointerleave", pointerLeaveHandler).on("pointerdown", pointerDownHandler).on("pointermove", pointerMoveHandler).on("pointerup", pointerUpHandler).on("pointerupoutside", pointerUpHandler);

        // 添加到画板层级结构中
        extendContainer.addChild(spriteContainer);

        /**
         * 绘制开始
         * @param {Object} event 事件对象
         * */
        function pointerDownHandler(event: Record<string, any>)
        {
            // 阻止事件
            if (event.button !== 0 || !CanvasPainting.enable)
            {
                // 阻止事件冒泡
                event.stopPropagation();

                return;
            }

            // 设置绘制状态
            isDrawing = true;

            // 获取当前鼠标位置
            const pos = event.getLocalPosition(spriteContainer);

            // 清除前次绘制残留
            graphics.clear();

            // 关键混合模式设置：擦除模式会减去alpha值
            graphics.blendMode = CanvasPainting.mode === "eraser" ? "erase" : "normal";

            // 画笔模式需要点击就绘制笔触
            if (CanvasPainting.mode === "brush")
            {
                // 获取当前配置
                const config = CanvasPainting.config.brush;

                // 开始绘制
                graphics.beginPath();

                // 绘制填充圆形
                graphics.circle(pos.x, pos.y, config.width / 2).fill({color: config.color, alpha: config.alpha});

                // 立即渲染到离屏纹理
                CanvasPainting.app.renderer.render({
                    container: graphics, target: drawingTexture, clear: false
                });
            }
            else
            {
                // 根据模式配置画笔参数
                configureGraphics(graphics);
            }

            // 设置绘制点
            graphics.clear().moveTo(pos.x, pos.y);
        }

        /**
         * 绘制过程中
         * @param {Object} event 事件对象
         * */
        function pointerMoveHandler(event: Record<string, any>): void
        {
            // 阻止事件
            if (!isDrawing || !CanvasPainting.enable)
            {
                // 阻止事件冒泡
                event.stopPropagation();

                return;
            }

            // 获取当前鼠标位置
            const pos = event.getLocalPosition(spriteContainer);

            // 添加路径点
            graphics.lineTo(pos.x, pos.y);

            // 执行路径绘制
            graphics.stroke();

            // 将临时绘图对象渲染到离屏纹理（实现绘制痕迹的累积）
            CanvasPainting.app.renderer.render({
                container: graphics,
                target: drawingTexture,
                clear: false
            });

            // 重置绘图对象（准备接收新的绘制路径）
            graphics.clear();

            // 根据模式配置画笔参数
            configureGraphics(graphics);

            // 设置绘制点
            graphics.moveTo(pos.x, pos.y);
        }

        /**
         * 绘制结束
         * */
        function pointerUpHandler(event: Record<string, any>): void
        {
            // 阻止事件
            if (!isDrawing || !CanvasPainting.enable)
            {
                // 阻止事件冒泡
                event.stopPropagation();

                return;
            }

            // 新增最后一次渲染保证完整性
            CanvasPainting.app.renderer.render({
                container: graphics, target: drawingTexture, clear: false
            });

            // 绘制结束
            isDrawing = false;

            // 清空临时绘图对象
            graphics.clear();
        }

        /**
         * 鼠标移入绘制区
         * */
        function pointerEnterHandler(event: Record<string, any>): void
        {
            // 绘制未激活时，阻止事件冒泡
            if (!CanvasPainting.enable)
            {
                // 阻止事件冒泡
                event.stopPropagation();

                return;
            }

            // 绘制时设置光标
            CanvasPainting.instance.drawingCursor(true);

            // 如果当前正在绘制
            if (isDrawing)
            {
                // 获取当前鼠标位置
                const pos = event.getLocalPosition(spriteContainer);

                graphics.clear();

                // 创建新的路径起点
                graphics.moveTo(pos.x, pos.y);

                // 立即绘制连接线段
                graphics.lineTo(pos.x, pos.y).stroke();

                // 新增过渡渲染逻辑
                CanvasPainting.app.renderer.render({
                    container: graphics, target: drawingTexture, clear: false
                });
            }
        }

        /**
         * 鼠标移开绘制区
         * */
        function pointerLeaveHandler(event: Record<string, any>): void
        {
            // 绘制未激活时，阻止事件冒泡
            if (!CanvasPainting.enable)
            {
                // 阻止事件冒泡
                event.stopPropagation();

                return;
            }

            // 设置光标
            CanvasPainting.instance.drawingCursor(false);

            // 如果当前正在绘制
            if (isDrawing)
            {
                // 获取最后有效坐标（使用事件离开时的位置）
                const pos = event.getLocalPosition(spriteContainer);

                // 添加终点并渲染
                graphics.lineTo(Math.max(0, Math.min(pos.x, backgroundImage.width)), // 限制在画布范围内
                    Math.max(0, Math.min(pos.y, backgroundImage.height))).stroke();

                // 将最后一笔渲染到纹理（新增代码）
                CanvasPainting.app.renderer.render({
                    container: graphics, target: drawingTexture, clear: false
                });

                // 清空临时绘图对象
                graphics.clear();
            }
        }

        /**
         * 绘制图形的工具函数
         * @param {Object} graphics 绘图对象
         * */
        function configureGraphics(graphics: Graphics): void
        {
            const config = CanvasPainting.mode === "brush" ? CanvasPainting.config.brush : CanvasPainting.config.eraser;

            graphics.setStrokeStyle({
                width: config.width,
                color: config.color,
                alpha: config.alpha, // 混合模式会处理透明度
                cap: "round",  // 线条端点圆形
                join: "round"  // 线条连接处圆形
            });
        }
    }

    /**
     * 光标状态管理
     * @param {Boolean} isHovering 是否正在绘制
     * */
    private drawingCursor(isHovering: boolean)
    {
        if (!CanvasPainting.app)
        {
            return;
        }

        // 根据操作模式获取尺寸
        const size = CanvasPainting.mode === "brush" ? CanvasPainting.config.brush.width : CanvasPainting.config.eraser.width;

        // 生成圆形光标
        const cursorCanvas = document.createElement("canvas");
        const ctx = cursorCanvas.getContext("2d", {willReadFrequently: true})!;

        // 设置画布尺寸（比光标大2像素用于描边）
        const canvasSize = size;
        cursorCanvas.width = canvasSize;
        cursorCanvas.height = canvasSize;

        // 绘制圆形
        ctx.beginPath();
        ctx.arc(canvasSize / 2, canvasSize / 2, size / 4, 0, Math.PI * 2);

        ctx.fillStyle = "#00000080"; // 半透明黑色
        ctx.fill();

        // 转换为CSS光标
        const dataURL = cursorCanvas.toDataURL();

        CanvasPainting.app.canvas.style.cursor = isHovering ? `url(${dataURL}) ${size / 2} ${size / 2}, auto` : "default";
    };
}

export default CanvasPainting;